package com.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.dto.MenuDto;
import com.dto.Menutest;
import com.dto.Meta;
import com.dto.RoleSmallDto;
import com.entity.Menu;
import com.entity.Role;
import com.entity.RoleAndMenu;
import com.exception.ParamException;
import com.repository.MenuAndRoleRepository;
import com.repository.MenuRepository;
import com.service.MenusService;
import com.service.RoleService;
import com.service.mapstruct.MenuMapper;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Yadasu
 * @date 2020/12/22 9:21
 */
@Service
@RequiredArgsConstructor
public class MenusServiceImpl implements MenusService {

    @Autowired
    private MenuRepository menuRepository;
    @Autowired
    private MenuAndRoleRepository menuAndRoleRepository;

    private final MenuMapper menuMapper;

    private final RoleService roleService;

    @Override
    public List<Menu> findMenuTop() {
        List<Menu> all = menuRepository.findAll();
        List<Menu> list = new ArrayList<>();
        for (Menu value : all) {
            Integer pid = value.getPid();
            List<Menu> parentByPid = menuRepository.findParentByPid(pid);
            Optional<Menu> byId = menuRepository.findById(pid);
            if (byId.isPresent()) {
                Menu menu = byId.get();
                menu.setChildren(parentByPid);
                list.add(menu);
            }
        }
        return list.stream().distinct().filter(menu -> {
                    Integer type = menu.getType();
                    return type == 0;
                }
        ).collect(Collectors.toList());
    }


    @Override
    public List<Menu> findMenuByUid(Role role) {
        List<RoleAndMenu> mid = menuAndRoleRepository.findAllByRid(role.getId());
        List<Menu> list = new ArrayList<>();
        for (RoleAndMenu roleAndMenu : mid) {
            if (menuRepository.findById(roleAndMenu.getMenuId()).isPresent()) {
                list.add(menuRepository.findById(roleAndMenu.getMenuId()).get());
            }
        }
        return list;
    }

    @Override
    public List<MenuDto> testMenu() {
        return null;
    }

    //生成菜单树
    @Override
    public List<Menutest> buildMenu(List<MenuDto> menuDtos) {
        List<Menutest> list = new ArrayList<>();
        menuDtos.forEach(menuDto -> {
            if (menuDto != null) {
                List<MenuDto> menuDtoList = menuDto.getChildren();
                Menutest menutest = new Menutest();
                menutest.setName(ObjectUtil.isNotEmpty(menuDto.getComponentName()) ? menuDto.getComponentName() : menuDto.getTitle());
                menutest.setPath(menuDto.getPid() == 0 ? "/" + menuDto.getPath() : menuDto.getPath());
                menutest.setHidden(menuDto.getHidden());
                if (menuDto.getPid() != null) {
                    menutest.setComponent(StringUtils.isEmpty(menuDto.getComponent()) ? "Layout" : menuDto.getComponent());
                    // 如果不是一级菜单，并且菜单类型为目录，则代表是多级菜单
                } else if (menuDto.getType() == 0) {
                    menutest.setComponent(StringUtils.isEmpty(menuDto.getComponent()) ? "ParentView" : menuDto.getComponent());
                } else if (StringUtils.isNoneBlank(menuDto.getComponent())) {
                    menutest.setComponent(menuDto.getComponent());
                }
                if (menuDto.getIcon() != null) {
                    menutest.setMeta(new Meta(menuDto.getTitle(), false, menuDto.getIcon()));
                }
                if (CollectionUtil.isNotEmpty(menuDtoList)) {
                    menutest.setAlwaysShow(true);
                    menutest.setRedirect("noredirect");
                    menutest.setChildren(buildMenu(menuDtoList));
                    // 处理是一级菜单并且没有子菜单的情况
                } else if (menuDto.getPid() == null) {
                    Menutest menutest1 = new Menutest();
                    menutest1.setMeta(menutest.getMeta());
                    menutest1.setPath(menuDto.getPath());
                    menutest.setName(null);
                    menutest.setMeta(null);
                    menutest.setComponent("Layout");
                    List<Menutest> list1 = new ArrayList<>();
                    list1.add(menutest1);
                    menutest.setChildren(list1);
                }
                list.add(menutest);
            }
        });
        return list;
    }

    @Override
    public List<MenuDto> findByUser(Long currentUserId) {
        List<RoleSmallDto> roles = roleService.findByUsersId(currentUserId);
        Set<Long> roleIds = roles.stream().map(RoleSmallDto::getId).collect(Collectors.toSet());
        LinkedHashSet<Menu> menus = menuRepository.findByRoleIdsAndTypeNot(roleIds, 2);
        return menus.stream().map(menuMapper::toDto).collect(Collectors.toList());
    }

    @Override
    public List<MenuDto> buildTree(List<MenuDto> menuDtos) {
        List<MenuDto> trees = new ArrayList<>();
        Set<Long> ids = new HashSet<>();
        for (MenuDto menuDTO : menuDtos) {
            if (menuDTO.getPid() == null) {
                trees.add(menuDTO);
            }
            for (MenuDto it : menuDtos) {
                if (menuDTO.getId().equals(it.getPid())) {
                    if (menuDTO.getChildren() == null) {
                        menuDTO.setChildren(new ArrayList<>());
                    }
                    menuDTO.getChildren().add(it);
                    ids.add(Long.valueOf(it.getId()));
                }
            }
        }
        if (trees.size() == 0) {
            trees = menuDtos.stream().filter(s -> !ids.contains(s.getId())).collect(Collectors.toList());
        }
        return trees;
    }

}
